package com.zx.eval.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.JsonObject;
import com.zx.common.utils.*;
import com.zx.eval.entity.*;
import com.zx.eval.service.*;
import io.swagger.models.auth.In;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.zx.eval.dao.EvalResultDao;


@Service("evalResultService")
public class EvalResultServiceImpl extends ServiceImpl<EvalResultDao, EvalResultEntity> implements EvalResultService {

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
//        IPage<EvalResultEntity> page = this.page(
//                new Query<EvalResultEntity>().getPage(params),
//                new QueryWrapper<EvalResultEntity>()
//                .orderByDesc("id")
//        );

        IPage<EvalResultEntity> page = new Query<EvalResultEntity>().getPage(params);
        page.setRecords(baseMapper.queryListPage(page, params));
        return new PageUtils(page);
    }

    @Override
    public boolean save(EvalResultEntity entity) {
        try {
            Integer tableId = entity.getTableId();
            if (tableId.equals(25) || tableId.equals(26)) {
                //感觉统合
                setAnswerStatisticOfFeelingIntegration(entity);
            } else if (tableId.equals(27) || tableId.equals(28) || tableId.equals(29) || tableId.equals(30) || tableId.equals(31)) {
                //儿童气质测评
                setAnswerStatisticOfTemperament(entity);
            } else if (tableId.equals(32)) {
                //儿童注意力测评表
                setAnswerStatisticOfAttention(entity);
            } else if (tableId.equals(33)) {
                //家庭环境
                setAnswerStatisticOfFamilyEnvironment(entity);
            } else if (tableId.equals(34)) {
                //童年逆境经验测评
                setChildhoodAdversity(entity);
            }
            QueryWrapper<EvalResultEntity> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("table_id", tableId);
            queryWrapper.eq("member_id", entity.getMemberId());
            List<EvalResultEntity> list = this.list(queryWrapper);
            entity.setCount(list.size() + 1);
          //  entity.setMemberId(1L);
          //  entity.setId(null);

            return super.save(entity);
        }catch (Exception e){
            e.printStackTrace();
        }
        return false;
    }

    private boolean saveMember(EvalResultEntity entity) {
        MemberEntity member = memberService.getById(entity.getMemberId());
        member.setBirthday(entity.getMemberBirth());
        member.setGender(entity.getMemberGender());
        member.setNation(entity.getNation());
        member.setParentName(entity.getParentName());
        member.setPhone(entity.getPhone());
        member.setName(entity.getMemberName());
        return memberService.updateById(member);
    }

    /**
     * 感觉统合测评算法
     */
    private void setAnswerStatisticOfFeelingIntegration(EvalResultEntity entity) {
        Integer tableId = entity.getTableId();

        QueryWrapper<EvalQuestionEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("table_id", tableId);
        queryWrapper.orderByAsc("question_id");
        List<EvalQuestionEntity> list = evalQuestionService.list(queryWrapper);
        Map<String, String> idDimensionMap = new HashMap<>();
        // 将每个题属于哪个维度放到map中。
        for (EvalQuestionEntity item : list) {
            idDimensionMap.put(item.getQuestionId() + "", item.getDimension());
        }

        // 获取每一个维度总分数
        Map<String, Integer> dimensionScoreMap = new HashMap<>();
        JSONArray jsonArray = JSONArray.parseArray(entity.getAnswer());
        for (int i = 0; i < jsonArray.size(); i++) {
            JSONObject jsonObject = jsonArray.getJSONObject(i);
            Set<String> strings = jsonObject.keySet();
            for (String key : strings) {
                String dimension = idDimensionMap.get(key);
                Integer oldScore = 0;
                if (dimensionScoreMap.containsKey(dimension)) {
                    oldScore = dimensionScoreMap.get(dimension);
                }
                dimensionScoreMap.put(dimension, oldScore + jsonObject.getInteger(key));
            }
        }

        int[] fs = {0,10, 20, 30, 40, 50,60};
        int[] array1 = {0, 31, 38, 44, 51, 58, 70};
        int[] array2 = {0, 50, 60, 70, 80, 90, 145};
        int[] array3 = {0, 26, 33, 39, 46, 52, 60};
        int[] array4 = {0, 13, 18, 23, 29, 33, 55};
        int[][] divider = {array1, array2, array3, array4};
        JSONArray resultArray = new JSONArray();
        for (String key : dimensionScoreMap.keySet()) {
            Integer score = dimensionScoreMap.get(key);
            int[] array = divider[Integer.valueOf(key) - 1];
            int index = getArrayIndex(array, score);
            int M = fs[index], N = fs[index + 1];
            //OriginalX  原始值 小  大
            int OriginalX = array[index], OriginalY = array[index + 1];
//            BigDecimal divisor = new BigDecimal((score - OriginalX) * (N - M));
//            BigDecimal dividend = new BigDecimal((OriginalY - OriginalX));
//            标准分值=M+((A-X)/(Y-X))*(N-M)
//            前庭平衡原始分值 37 分，落在原始分范围(31，38)，对应标准分范围(10， 20)
//            标准分值=10+((37-31)/(38-31))*(20-10)=19<20 为重度前庭失衡。
            BigDecimal divisor = new BigDecimal((OriginalY -OriginalX));
            BigDecimal dividend = new BigDecimal((score - OriginalX));
           // int bz = M + dividend.divide(divisor, RoundingMode.HALF_UP).intValue() * (N - M);

            int bz = M + dividend.divide(divisor ,1, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(N - M)).intValue();
            JSONObject object = new JSONObject();
            object.put("dimension", key);
            object.put("bzScore", bz);
            object.put("ysScore", score);
            resultArray.add(object);
        }
        entity.setAnswerStatistic(resultArray.toJSONString());
    }

    private static int getArrayIndex(int[] array, int score) {
        for (int i = 0; i < array.length; i++) {
            if (score <= array[i]) {
                return i - 1;
            }
        }
        return array.length;
    }

    /**
     * 注意力测评算法
     * 项目 分数 参考标准
     */
    private void setAnswerStatisticOfAttention(EvalResultEntity entity) {
        Integer tableId = entity.getTableId();

        QueryWrapper<EvalQuestionEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("table_id", tableId);
        queryWrapper.orderByAsc("question_id");
        List<EvalQuestionEntity> list = evalQuestionService.list(queryWrapper);
        Map<String, String> idDimensionMap = new HashMap<>();
        // 将每个题属于哪个维度放到map中。
        for (EvalQuestionEntity item : list) {
            idDimensionMap.put(item.getQuestionId() + "", item.getDimension());
        }

        // 获取每一个维度总分数
        Map<String, Integer> dimensionScoreMap = new HashMap<>();
        JSONArray jsonArray = JSONArray.parseArray(entity.getAnswer());
        for (int i = 0; i < jsonArray.size(); i++) {
            JSONObject jsonObject = jsonArray.getJSONObject(i);
            Set<String> strings = jsonObject.keySet();
            for (String key : strings) {
                String dimension = idDimensionMap.get(key);
                Integer oldScore = 0;
                if (dimensionScoreMap.containsKey(dimension)) {
                    oldScore = dimensionScoreMap.get(dimension);
                }
                int currScore = jsonObject.getInteger(key);
                currScore = filterScore(dimension, currScore);
                dimensionScoreMap.put(dimension, oldScore + currScore);
            }
        }

        JSONArray resultArray = new JSONArray();
        for (String s : dimensionScoreMap.keySet()) {
            JSONObject object = new JSONObject();
            object.put(s, dimensionScoreMap.get(s));
            resultArray.add(object);
        }
        entity.setAnswerStatistic(resultArray.toJSONString());
    }

    /**
     * 分数 过虑器
     * @param dimension 维度
     * @param score 分数
     * @return
     * 项目 分数 参考标准
     * 注意缺陷（1-9） 2 或 3 分的项目分数 6+1 分
     * 多动冲动（10-18） 2 或 3 分的项目分数 6+1 分
     * 混合（1-18） 总的症状分数 12+1 分
     * 对立违抗障碍（19-26） 2 或 3 分的项目分数 4+1 分
     * 品行（27-38） 2 或 3 分的项目分数 3+1 分
     * 焦虑/抑郁（39-45） 2 或 3 分的项目分数 3+1 分
     * 学习及人际关系（46-53） 4 或 5 分的项目分数
     */
    private int filterScore(String dimension, int score){
        int nScore = 0;
        if(dimension != null && dimension.equals("6")){
            //学习及人际关系（46-53） 4 或 5 分的项目分数
            if(score ==4 || score == 5){
                nScore = score;
            }
        }else {
            //其它维度只取 2 或 3 分的项目分数 6+1 分
            if(score ==2 || score == 3){
                nScore = score;
            }
        }

        return nScore;
    }
    /**
     * 家庭环境测评算法
     */
    private void setAnswerStatisticOfFamilyEnvironment(EvalResultEntity entity) {
        Integer tableId = entity.getTableId();
        EvalTableEntity evalObj = evalTableService.getById(tableId);
        String [] dimenArr = evalObj.getSortNum().split("&");

        JSONArray jsonArray = JSONArray.parseArray(entity.getAnswer());

        JSONArray resultArray = new JSONArray();
        for (String s : dimenArr) {
            JSONObject object = new JSONObject();
            //每个维度得分
            int dimeScore = FamilyEnvironmentDimensionScore(Integer.valueOf(s), jsonArray);
            object.put(s, dimeScore);
            resultArray.add(object);
        }

        entity.setAnswerStatistic(resultArray.toJSONString());
    }

    /**
     * 童年逆境经验测评
     * @param entity
     */
    private void setChildhoodAdversity(EvalResultEntity entity){
        Integer tableId = entity.getTableId();
        EvalTableEntity evalObj = evalTableService.getById(tableId);
      //  String [] dimenArr = evalObj.getSortNum().split("&");

        JSONArray answerJsonArr = JSONArray.parseArray(entity.getAnswer());

        JSONArray resultArray = new JSONArray();
        //没有维度
        for(int i=0; i<answerJsonArr.size();i++){
            JSONObject jObject = new JSONObject();
            int answerVal = JsonToInt(i+1,answerJsonArr);
            String sIndex = String.valueOf(i+1);
            jObject.put(sIndex, answerVal);
            resultArray.add(jObject);
        }
        entity.setAnswerStatistic(resultArray.toJSONString());
    }


    // 家庭环境算法 返回 维度分数
    public int FamilyEnvironmentDimensionScore(int dIndex, JSONArray answerArr){

        int result  = 0;
        switch (dIndex) {
            case 1:
                //    亲密度= (I~11—1)+(I~41—1)+(I~61—1)
                //    一[(I~1—2)+(I~21—2)+(I~31—2)+(I~51—2)+(I~71—2)+(I~81—2)]
                result = ((JsonToInt(11,answerArr)-1) +(JsonToInt(41,answerArr)-1) +(JsonToInt(61,answerArr)-1))
                        - ((JsonToInt(1,answerArr)-2) + (JsonToInt(21,answerArr)-2)+ (JsonToInt(31,answerArr)-2)+
                                (JsonToInt(51,answerArr)-2) + (JsonToInt(71,answerArr)-2)+ (JsonToInt(81,answerArr)-2));
                return result;
            case 2:
                // 情感表达= [(I~2—1)+(I~22—1)+(I~52—1)+(I~72—1)
                //    一[I(I~12—2)+(I~32—2)+(I~42—2)+(I~62—2)+(I~82—2)]
                result = ((JsonToInt(2,answerArr)-1) +(JsonToInt(22,answerArr)-1) +(JsonToInt(52,answerArr)-1)+(JsonToInt(72,answerArr)-1))
                        -  ((JsonToInt(12,answerArr)-2) + (JsonToInt(32,answerArr)-2)+ (JsonToInt(42,answerArr)-2)+
                                (JsonToInt(62,answerArr)-2) + (JsonToInt(82,answerArr)-2));
                return result;
            case 3:
                // 矛盾性 = (I~13—1)+(I~33—1)+(I~63—1)
                //    一 [(I~3—2)+(I~23—2)+(I~43—2)+(I~53—2)+(I~73—2)+(I~83—2)]
                result = ((JsonToInt(13,answerArr)-1) +(JsonToInt(33,answerArr)-1) +(JsonToInt(63,answerArr)-1))
                        -  ((JsonToInt(3,answerArr)-2) + (JsonToInt(23,answerArr)-2)+ (JsonToInt(43,answerArr)-2)+
                                (JsonToInt(53,answerArr)-2) + (JsonToInt(73,answerArr)-2)+ (JsonToInt(83,answerArr)-2));
                return result;
            case 4:
                // 独立性 = (I~4—1)+(I~54—1)一
                // [(I~14—2)+(I~24—2)+(I~34—2)+(I~44—2)+(I~64—2)+(I~74—2)+(I~84—2)]
                result = ((JsonToInt(4,answerArr)-1) +(JsonToInt(54,answerArr)-1))
                        - ((JsonToInt(14,answerArr)-2)+(JsonToInt(24,answerArr)-2)+(JsonToInt(34,answerArr)-2)+
                        (JsonToInt(44,answerArr)-2) + (JsonToInt(64,answerArr)-2)+ (JsonToInt(74,answerArr)-2)+
                                (JsonToInt(84,answerArr)-2));
                return result;
            case 5:
                // 成功性 = (I~55—1)+(I~65—1)
                // 一[(I~5—2)—(I~15—2)+(I~25—2)+(I~35—2)+(I~45—2)+(I~75—2)+(1~85—2)]
                result = ((JsonToInt(55,answerArr)-1) +(JsonToInt(65,answerArr)-1))
                        - ((JsonToInt(5,answerArr)-2)+(JsonToInt(15,answerArr)-2)+
                        (JsonToInt(25,answerArr)-2) + (JsonToInt(35,answerArr)-2)+ (JsonToInt(45,answerArr)-2)+
                        (JsonToInt(75,answerArr)-2) + (JsonToInt(85,answerArr)-2));
                return result;
            case 6:
                // 知识性 = (I~16—1)+(I~36—1)+(I~46—1)+(I~76—1)
                //    一[(I~6—2)+(I~26—2)+(I~56—2)+(I~66—2)+(I~86—2)]
                result = ((JsonToInt(16,answerArr)-1) +(JsonToInt(36,answerArr)-1) +(JsonToInt(46,answerArr)-1)+(JsonToInt(76,answerArr)-1))
                        -  ((JsonToInt(6,answerArr)-2) + (JsonToInt(26,answerArr)-2)+ (JsonToInt(56,answerArr)-2)+
                        (JsonToInt(66,answerArr)-2) + (JsonToInt(86,answerArr)-2));
                return result;
            case 7:
                // 娱乐性 = (I~7—1)+(I~27—2)+(I~57—1)+(I~87—1)
                //    一[(I~17—2)+(I~37—2)+(I~47—2)+(I~67—2)+(I~77—2)]
                result = ((JsonToInt(7,answerArr)-1) +(JsonToInt(27,answerArr)-2) +(JsonToInt(57,answerArr)-1)+(JsonToInt(87,answerArr)-1))
                        - ((JsonToInt(17,answerArr)-2) + (JsonToInt(37,answerArr)-2)+ (JsonToInt(47,answerArr)-2)+
                        (JsonToInt(67,answerArr)-2) + (JsonToInt(77,answerArr)-2));
                return result;
            case 8:
                // 道德宗教观=(I~18—1)+(I~38—1)+(I~88—1)
                // 一[(I~8—2)+(I~28—2)+(I~48—2)+(I~58—2)+(I~58—2)+(I~68—2)+(I~78—2)]
                result = ((JsonToInt(18,answerArr)-1) +(JsonToInt(38,answerArr)-1) +(JsonToInt(88,answerArr)-1))
                        - ((JsonToInt(8,answerArr)-2) + (JsonToInt(28,answerArr)-2)+ (JsonToInt(48,answerArr)-2)+
                        (JsonToInt(58,answerArr)-2) + (JsonToInt(68,answerArr)-2)+ (JsonToInt(78,answerArr)-2));
                return result;
            case 9:
                // 组织性 = (I~29—1)+(I~49—1)+(I~79—1)
                // 一[(I~19—2)+(I~39—2)+ (I~59—2)+(I~69—2)+(I~89—2)]
                result = ((JsonToInt(29,answerArr)-1) +(JsonToInt(49,answerArr)-1) +(JsonToInt(79,answerArr)-1))
                        - ((JsonToInt(19,answerArr)-2) + (JsonToInt(39,answerArr)-2)+ (JsonToInt(59,answerArr)-2)+
                        (JsonToInt(69,answerArr)-2) + (JsonToInt(89,answerArr)-2));
                return result;
            case 10:
                //    控制性 = (I~10 一 1)+(I~20—1)+(I~60—1)+(I~70 一 1)一
                //[(I~30 一 2)+(I~40 一 2)+(I~50—2)+(I~80—2)+(I~90 一 2)]
                result = ((JsonToInt(10,answerArr)-1) +(JsonToInt(20,answerArr)-1) +(JsonToInt(60,answerArr)-1)+(JsonToInt(70,answerArr)-1))
                        -  ((JsonToInt(30,answerArr)-2) + (JsonToInt(40,answerArr)-2)+ (JsonToInt(50,answerArr)-2)+
                        (JsonToInt(80,answerArr)-2) + (JsonToInt(90,answerArr)-2));
                return result;
        }
        return result;
    }


    private int JsonToInt(int index, JSONArray answerArr){
        return Integer.parseInt(answerArr.getJSONObject(index-1).get(index).toString());
    }
    /**
     * 气质测评算法
     */
    private void setAnswerStatisticOfTemperament(EvalResultEntity entity) {
        Integer tableId = entity.getTableId();

        QueryWrapper<EvalQuestionEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("table_id", tableId);
        queryWrapper.orderByAsc("question_id");
        List<EvalQuestionEntity> list = evalQuestionService.list(queryWrapper);
        Map<String, String> idDimensionMap = new HashMap<>();
        // 将每个题属于哪个维度放到map中。
        for (EvalQuestionEntity item : list) {
            String dimension = item.getDimension();
            String groupName = item.getGroupName();
            if ("0".equals(groupName)) {
                dimension = dimension + "*";
            }
            idDimensionMap.put(item.getQuestionId() + "", dimension);
        }

        // 获取每一个维度总分数
        Map<String, Integer> dimensionScoreMap = new HashMap<>();
        Map<String, Integer> dimensionCountMap = new HashMap<>();
        JSONArray jsonArray = JSONArray.parseArray(entity.getAnswer());
        for (int i = 0; i < jsonArray.size(); i++) {
            JSONObject jsonObject = jsonArray.getJSONObject(i);
            Set<String> strings = jsonObject.keySet();
            for (String key : strings) {
                String dimension = idDimensionMap.get(key);
                Integer oldScore = 0;
                if (dimensionScoreMap.containsKey(dimension)) {
                    oldScore = dimensionScoreMap.get(dimension);
                }
                Integer score = jsonObject.getInteger(key);
                dimensionScoreMap.put(dimension, oldScore + score);

                if (score != 0) {
                    Integer oldCount = 0;
                    if (dimensionCountMap.containsKey(dimension)) {
                        oldCount = dimensionCountMap.get(dimension);
                    }
                    dimensionCountMap.put(dimension, oldCount + 1);
                }
            }
        }

        JSONArray resultArray = new JSONArray();
        for (String s : dimensionScoreMap.keySet()) {
            Integer score = dimensionScoreMap.get(s);
            Integer count = dimensionCountMap.get(s);
            double A = new BigDecimal(score).divide(new BigDecimal(count), 2, RoundingMode.HALF_UP).doubleValue();
            JSONObject object = new JSONObject();
            object.put(s, A);
            resultArray.add(object);
        }
        entity.setAnswerStatistic(resultArray.toJSONString());
    }

    @Override
    public JSONObject getReportByResultId(Integer id, boolean isReport) {
        JSONObject reportData = new JSONObject();
        EvalResultEntity evalResultEntity = baseMapper.selectById(id);
        Integer tableId = evalResultEntity.getTableId();
        if (tableId.equals(25) || tableId.equals(26)) {
            reportData = getReportOfFeelingIntegration(evalResultEntity, isReport);
        } else if (tableId.equals(27) || tableId.equals(28) || tableId.equals(29) || tableId.equals(30) || tableId.equals(31)) {
            reportData = getReportOfTemperament(evalResultEntity, isReport);
        } else if (tableId.equals(32)) {
            reportData = getReportOfAttention(evalResultEntity, isReport);
        } else if (tableId.equals(33)) {
            reportData = getReportOfFamilyEnvironment(evalResultEntity, isReport);
        }else if (tableId.equals(34)) {
            reportData = getReportOfChildhoodAdversity(evalResultEntity, isReport);
        }
        String format = DateUtils.format(evalResultEntity.getOptime(), DateUtils.DATE_PATTERN);
        String remainDateToString = DateDaySub.remainDateToString(evalResultEntity.getMemberBirth(), format);
        evalResultEntity.setYuefen(remainDateToString);
        reportData.put("info", evalResultEntity);
        return reportData;
    }

    @Override
    public JSONArray getResultList(Long memberId) {
        QueryWrapper<EvalResultEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("member_id", memberId);
        List<EvalResultEntity> resultList = this.list(queryWrapper);
        Map<Integer, List<EvalResultEntity>> tableIdResultMap = new HashMap<>();
        for (EvalResultEntity evalResultEntity : resultList) {
            Integer tableId = evalResultEntity.getTableId();
            List<EvalResultEntity> temp = new ArrayList<>();
            if (tableIdResultMap.containsKey(tableId)) {
                temp = tableIdResultMap.get(tableId);
            }
            temp.add(evalResultEntity);
            tableIdResultMap.put(tableId, temp);
        }
//        QueryWrapper<EvalTableEntity> queryWrapperTable = new QueryWrapper<>();
//        queryWrapperTable.lt("category", 3);
//        queryWrapperTable.eq("display", 1);
//        queryWrapperTable.orderByAsc("priority");
//        List<EvalTableEntity> tableList = evalTableService.list(queryWrapperTable);
//        Map<Integer, EvalTableEntity> tableIdEntityMap = new HashMap<>();
//        for (EvalTableEntity entity : tableList) {
//            tableIdEntityMap.put(entity.getId(), entity);
//        }
        JSONArray result = new JSONArray();
        for (Integer integer : tableIdResultMap.keySet()) {
            JSONObject item = new JSONObject();
            List<EvalResultEntity> resultEntities = tableIdResultMap.get(integer);
           // EvalTableEntity entity = tableIdEntityMap.get(integer);
            EvalTableEntity entity = evalTableService.getById(integer);
            item.put("name",entity.getName());
            item.put("datas",resultEntities);
            result.add(item);
        }

        return result;
    }

    /**
     * 童年逆境经验测评
     * @param entity
     * @param isReport
     * @return
     */
    private JSONObject getReportOfChildhoodAdversity(EvalResultEntity entity, boolean isReport) {
        JSONObject result = new JSONObject();
        String answerStatistic = entity.getAnswerStatistic();
        JSONArray jsonArray = JSONArray.parseArray(answerStatistic);
        ArrayList<String> scoreArray = new ArrayList<>();
        JSONArray jsonArrReport = new JSONArray();
        for (int i = 0; i < jsonArray.size(); i++) {
            JSONObject jsonObject = jsonArray.getJSONObject(i);
            String  score = jsonObject.getString(String.valueOf(i+1));
            scoreArray.add(score);

        }
        result.put("scoreArray", scoreArray);


        EvalTableEntity table = evalTableService.getById(entity.getTableId());
        String[] sortCnArray = table.getSortCn().split("&");
        result.put("cnArray", sortCnArray);
        result.put("report", jsonArrReport);
        return result;
    }
    /**
     * 家庭环境测评报告 中国常模
     *     <i-col span="2" i-class="col-class">5.8-9.6</i-col>
     *     <i-col span="3" i-class="col-class">4.1-7.5</i-col>
     *     <i-col span="2" i-class="col-class">0.3-4.1</i-col>
     *     <i-col span="2" i-class="col-class">4.4-7.2</i-col>
     *     <i-col span="2" i-class="col-class">5.1-8.5</i-col>
     *     <i-col span="2" i-class="col-class">3.5-7.7</i-col>
     *     <i-col span="2" i-class="col-class">2.9-6.9</i-col>
     *     <i-col span="3" i-class="col-class">3.9-6.7</i-col>
     *     <i-col span="2" i-class="col-class">4.9-8.5</i-col>
     *     <i-col span="2" i-class="col-class">1.8-5.4</i-col>
     */
    private JSONObject getReportOfFamilyEnvironment(EvalResultEntity entity, boolean isReport) {
        JSONObject result = new JSONObject();
        String answerStatistic = entity.getAnswerStatistic();
        JSONArray jsonArray = JSONArray.parseArray(answerStatistic);
        ArrayList<String> scoreArray = new ArrayList<>();
        JSONArray jsonArrReport = new JSONArray();
        for (int i = 0; i < jsonArray.size(); i++) {
            JSONObject jsonObject = jsonArray.getJSONObject(i);
            for (String s : jsonObject.keySet()) {
                String score = jsonObject.getString(s);
                scoreArray.add(score);
                JSONObject object = new JSONObject();
                if(isReport) {
                    object.put("report", this.getDimensionReport(entity.getTableId(), Integer.parseInt(s), Integer.parseInt(score), ""));
                }
                jsonArrReport.add(object);
            }
        }
        result.put("scoreArray", scoreArray);
        String[] modulus = {"7.7±1.9", "5.8±1.7", "2.2±1.9", "5.8±1.4", "6.8±1.7", "5.6±2.1", "4.9±2.0", "5.3±1.4", "6.7±1.8", "3.6±1.8"};
        String[] norms = {"5.8-9.6", "4.1-7.5", "0.3-4.1", "4.4-7.2", "5.1-8.5", "3.5-7.7", "2.9-6.9", "3.9-6.7", "4.9-8.5", "1.8-5.4"};

        result.put("modulus", modulus);
        result.put("norms", norms);
        EvalTableEntity table = evalTableService.getById(entity.getTableId());
        String[] sortCnArray = table.getSortCn().split("&");
        result.put("cnArray", sortCnArray);
        result.put("report", jsonArrReport);
        return result;
    }

    /**
     * 感觉统合测评报告
     */
    private JSONObject getReportOfFeelingIntegration(EvalResultEntity entity, boolean isReport) {
        JSONObject result = new JSONObject();
        Integer tableId = entity.getTableId();
        EvalTableEntity table = evalTableService.getById(tableId);
        String[] sortCnArray = table.getSortCn().split("&");
        String answerStatistic = entity.getAnswerStatistic();
        JSONArray jsonArray = JSONArray.parseArray(answerStatistic);
        JSONArray tableArray = new JSONArray();
        for (int i = 0; i < jsonArray.size(); i++) {
            JSONObject jsonObject = jsonArray.getJSONObject(i);
            JSONObject rowData = new JSONObject();
            rowData.put("cn", sortCnArray[i]);
            rowData.put("ysScore", jsonObject.getInteger("ysScore"));
            rowData.put("bzScore", jsonObject.getInteger("bzScore"));
            Integer dimension = jsonObject.getInteger("dimension");
            rowData.put("result", getMSOfFeelingIntegrationItem(jsonObject.getString("dimension"), jsonObject.getInteger("bzScore")));
            if(isReport) {
                rowData.put("report", getDimensionReport(tableId, dimension, jsonObject.getInteger("bzScore"), ""));
            }
            tableArray.add(rowData);
        }
        result.put("tableData", tableArray);
        return result;
    }

    /**
     *
     * @param tableId  量表
     * @param dimension 维度
     * @param score 分数
     * @return
     */
    private String getDimensionReport(Integer tableId, Integer dimension, Integer score, String cnResult){
        String result = "";
        EvalMatchEntity evalMatch = getMatch(tableId,dimension);
        if (tableId.equals(25) || tableId.equals(26)) {
            //感觉统合
            if(score <= 40){
                result = evalMatch.getMemo() + evalMatch.getDes1();
            }else {
                result = evalMatch.getMemo() + evalMatch.getDes2();
            }
        } else if (tableId.equals(27) || tableId.equals(28) || tableId.equals(29) || tableId.equals(30) || tableId.equals(31)) {
            //儿童气质测评
            if (dimension ==1 || dimension ==5) {
                if (cnResult.equals("较弱")) {
                    result = evalMatch.getMemo() + evalMatch.getDes3();
                }else if(cnResult.equals("较高") || cnResult.equals("较强")){
                    result = evalMatch.getMemo() + evalMatch.getDes1();
                }else {
                    result = evalMatch.getMemo() + evalMatch.getDes2();
                }
            } else if (dimension ==2 || dimension ==4){
                if (cnResult.equals("较强")) {
                    result = evalMatch.getMemo() + evalMatch.getDes1();
                }else if(cnResult.equals("较弱")){
                    result = evalMatch.getMemo() + evalMatch.getDes3();
                }else {
                    result = evalMatch.getMemo() + evalMatch.getDes2();
                }
            }else if (dimension ==3 || dimension ==6 || dimension ==8){
                if (cnResult.equals("易接近") || cnResult.equals("较积极") || cnResult.equals("较易分散")) {
                    result = evalMatch.getMemo() + evalMatch.getDes1();
                }else if(cnResult.equals("易退缩") || cnResult.equals("较消极") || cnResult.equals("不易分散")){
                    result = evalMatch.getMemo() + evalMatch.getDes3();
                }else {
                    result = evalMatch.getMemo() + evalMatch.getDes2();
                }
            }else if (dimension ==7 || dimension ==9){
                if (cnResult.equals("较高") ) {
                    result = evalMatch.getMemo() + evalMatch.getDes1();
                }else if(cnResult.equals("较低") ){
                    result = evalMatch.getMemo() + evalMatch.getDes3();
                }else {
                    result = evalMatch.getMemo() + evalMatch.getDes2();
                }
            }

        } else if (tableId.equals(32)) {
            //儿童注意力测评表
            if (dimension ==1 || dimension ==2) {
                if (score >= 7 && score <= 8) {
                    result = evalMatch.getDes1() + "</br>" + evalMatch.getMemo();
                }else if(score >=9){
                    result = evalMatch.getDes2() + "</br>" + evalMatch.getMemo();
                }else {
                    result = evalMatch.getDes3() + "</br>" + evalMatch.getMemo();
                }
            } else if (dimension ==3){
                if (score >= 5 && score <= 6) {
                    result = evalMatch.getDes1() + "</br>" + evalMatch.getMemo();
                }else if(score >= 7 ){
                    result = evalMatch.getDes2() + "</br>" + evalMatch.getMemo();
                }else {
                    result = evalMatch.getDes3() + "</br>" + evalMatch.getMemo();
                }
            }else if (dimension ==4 || dimension ==5){
                if (score >= 5 && score <= 6) {
                    result = evalMatch.getDes1() + "</br>" + evalMatch.getMemo();
                }else if(score >= 7){
                    result = evalMatch.getDes2() + "</br>" + evalMatch.getMemo();
                }else {
                    result = evalMatch.getDes3() + "</br>" + evalMatch.getMemo();
                }
            }

        } else if (tableId.equals(33)) {
            //家庭环境
            if(dimension ==1 || dimension == 5 || dimension == 9){
                //亲密度  成功性    组织性
                if(score <= 5){
                    result = evalMatch.getDes1();

                }else if(score >=6 && score <=8){
                    result = evalMatch.getDes2();

                }else if(score >= 9){
                    result = evalMatch.getDes3();

                }
            }else if(dimension ==2 || dimension ==8){
                //情感表达  道德宗教观
                if(score <=4 ){
                    result = evalMatch.getDes1();

                }else if(score >=5 && score <=7){
                    result = evalMatch.getDes2();

                }else if(score >= 8){
                    result = evalMatch.getDes3();

                }
            }else if(dimension ==3){
                //矛盾性
                if(score <=1 ){
                    result = evalMatch.getDes1();

                }else if(score >=2 && score <=5){
                    result = evalMatch.getDes2();

                }else if(score >= 6){
                    result = evalMatch.getDes3();

                }
            }else if(dimension ==4  || dimension ==6){
                //  独立性  文化性
                if(score <=3 ){
                    result = evalMatch.getDes1();

                }else if(score >=4 && score <=7){
                    result = evalMatch.getDes2();

                }else if(score >= 8){
                    result = evalMatch.getDes3();

                }
            }else if(dimension ==7){
                //  娱乐性
                if(score <=3 ){
                    result = evalMatch.getDes1();

                }else if(score >=4 && score <=6){
                    result = evalMatch.getDes2();

                }else if(score >= 7){
                    result = evalMatch.getDes3();

                }
            }else if(dimension ==10){
                //  控制性
                if(score <=2 ){
                    result = evalMatch.getDes1();

                }else if(score >=3 && score <=5){
                    result = evalMatch.getDes2();

                }else if(score >= 6){
                    result = evalMatch.getDes3();

                }
            }
        }
        return result;
    }


    /**
     * 只返回维度结果，没有说明，给手机端使用
     * @param tableId
     * @param dimension
     * @param score
     * @param cnResult
     * @return
     */
    private String getDimensionReportOnlyResult(Integer tableId, Integer dimension, Integer score, String cnResult){
        String result = "";
        EvalMatchEntity evalMatch = getMatch(tableId,dimension);
        if (tableId.equals(32)) {
            //儿童注意力测评表
            if (dimension ==1 || dimension ==2) {
                if (score >= 7 && score <= 8) {
                    result = evalMatch.getDes1() ;
                }else if(score >=9){
                    result = evalMatch.getDes2() ;
                }else {
                    result = evalMatch.getDes3() ;
                }
            } else if (dimension ==3){
                if (score >= 5 && score <= 6) {
                    result = evalMatch.getDes1() ;

                }else if(score >= 7){
                    result = evalMatch.getDes2() ;

                }else {
                    result = evalMatch.getDes3() ;
                }
            }else if (dimension ==4 || dimension ==5){
                if (score >= 5 && score <= 6) {
                    result = evalMatch.getDes1() ;
                }else if(score >= 7){
                    result = evalMatch.getDes2() ;
                }else {
                    result = evalMatch.getDes3() ;
                }
            }

        }
        result = result.replace("<p>","");
        result = result.replace("</p>","");
        return result;
    }
    /**
     *
     * @param tableId
     * @param dimension
     * @return
     */
    private EvalMatchEntity getMatch(Integer tableId, Integer dimension){
        EvalMatchEntity  matchObj = null;
        Integer nTableId = tableId;
        String sPrefix = tableId + "_" + dimension;
        if (tableId.equals(25) || tableId.equals(26)) {
            nTableId = 25;
        } else if (tableId.equals(27) || tableId.equals(28) || tableId.equals(29) || tableId.equals(30) || tableId.equals(31)) {
            nTableId = 29;
        } else if (tableId.equals(32)) {
            nTableId = 32;
        } else if (tableId.equals(33)) {
            nTableId = 33;
        }

        if (redisUtils.hasKey(RedisUtils.keyPrefix.eval_report_dimension.toString() + sPrefix)){
            return redisUtils.get(RedisUtils.keyPrefix.eval_report_dimension.toString() + sPrefix, EvalMatchEntity.class);
        }else {
            QueryWrapper<EvalMatchEntity> matchQuery = new QueryWrapper<>();
            matchQuery.eq("table_id", nTableId);
            matchQuery.eq("code", dimension);
            matchObj = evalMatchService.getOne(matchQuery);

            redisUtils.set(RedisUtils.keyPrefix.eval_report_dimension.toString() + sPrefix, matchObj);
        }
        return matchObj;
    }
    /**
     * 气质测评报告
     */
    private JSONObject getReportOfTemperament(EvalResultEntity entity, boolean isReport) {
        JSONObject result = new JSONObject();
        Integer tableId = entity.getTableId();
        EvalTableEntity table = evalTableService.getById(tableId);
        String[] sortCnArray = table.getSortCn().split("&");
        Double[] standardArr = new Double[sortCnArray.length];
        Double[] oneSDArr = new Double[sortCnArray.length];
        Double[] scoreArr = new Double[sortCnArray.length];
        QueryWrapper<DictExtEntity> queryWrapper = new QueryWrapper<>();
        Date optime = entity.getOptime();
        String memberBirth = entity.getMemberBirth();
        Date date = DateUtils.stringToDate(memberBirth, DateUtils.DATE_PATTERN);
        Integer months = getMonths(date, optime);
        queryWrapper.le("key2", months);
        queryWrapper.ge("key3", months);
        queryWrapper.eq("key1", entity.getMemberGender());
        queryWrapper.orderByAsc("priority");
        List<DictExtEntity> list = dictExtService.list(queryWrapper);
        String answerStatistic = entity.getAnswerStatistic();
        JSONArray jsonArray = JSONArray.parseArray(answerStatistic);
        ArrayList<JSONObject> objects = new ArrayList<>();
        for (int i = 0; i < jsonArray.size(); i++) {
            DictExtEntity dictExtEntity = list.get(i);
            String jsonValue = dictExtEntity.getJsonValue();
            JSONObject item = JSONObject.parseObject(jsonValue);
            Double aa1SD = item.getDouble("AA1SD");
            Double as1Sd = item.getDouble("AS1SD");

            //标准值
            Double aValue = Double.valueOf(dictExtEntity.getValue());
            JSONObject jsonObject = jsonArray.getJSONObject(i);
            JSONObject object = new JSONObject();
            String bzz = dictExtEntity.getValue() + "/(" + as1Sd + "-" + aa1SD + ")";
            object.put("cn", sortCnArray[i]);
            object.put("bzz", bzz);
            standardArr[i] = aValue;
            oneSDArr[i] = aa1SD;
            for (String s : jsonObject.keySet()) {
                String score = jsonObject.getString(s);

                String ms = temperamentCnType(Integer.valueOf(s),score, aValue, aa1SD, as1Sd);

                object.put("score", score);
                object.put("ms", ms);
                scoreArr[i] = Double.parseDouble(score);
                if(isReport) {
                    object.put("report", getDimensionReport(tableId, Integer.parseInt(s), jsonObject.getInteger("bzScore"), ms));
                }
            }
            objects.add(object);
        }
        String report = temperamentReportTxt(scoreArr,standardArr, oneSDArr);
        result.put("tableData", objects);
        result.put("report", report);
        return result;
    }

    /**
     * 1-----活动水平,2-----节律性,3-----趋避性,4-----适应性，5-----反应强度，6-----情绪本质
     * 7-----坚持性，8-----注意分散度，9-----反应阈
     * 分型依据:节律性、趋避性、适应性、反应强度、情绪本质
     *
     * @param scores  分数
     * @param standards 标准值 = 平均值
     * @param oneSDArr 一个校准差
     * @return
     */
    private String temperamentReportTxt(Double[] scores, Double[] standards, Double[] oneSDArr){
        // 除了中间偏易外，其余都是与。
        String result = "";
        //大于平均值数量
        int greatStandardCount = 0;
        //大于一个标准差数量
        int greatOneSDCount = 0;
        // 即大于平均值又大于标准值的数量
        int doubleGreatCount = 0;

        // 反应强度  趋避性  适应性
        boolean bResponse = false, bPhobotaxis = false, bAdaptation=false;
        // 只取  分型依据:2节律性、3趋避性、4适应性、5反应强度、6情绪本质
        for (int i=1; i<6; i++){
            if (scores[i] > standards[i]){
                greatStandardCount ++;
                if(i==4){
                    bResponse = true;
                }
            }
            if (scores[i] > oneSDArr[i]){
                greatOneSDCount ++;
                if(i==2){
                    bPhobotaxis = true;
                }else if(i==3){
                    bAdaptation = true;
                }
            }
            if (scores[i] > standards[i] && scores[i] > oneSDArr[i]){
                doubleGreatCount ++;
            }
        }


        if (greatStandardCount <=2 && greatOneSDCount ==0){
            /**
             * 易养性:
             * –五个维度得分大于平均值的维度不超过两项
             * –没有一个维度大于一个标准差
             */
            result = "易养性";
        }else if (greatStandardCount >=4 && bResponse && greatOneSDCount>=2){
            /**
             * 难养性:
             * – 4 或 5 个维度得分大于平均值，
             * –必须包括反应强度
             * –有两个维度的得分大于一个标准差
             */
            result = "难养性";
        }else if((greatStandardCount ==3  || greatStandardCount ==4 ) && (bPhobotaxis || bAdaptation) && scores[0] <= (standards[0] + (oneSDArr[0]-standards[0])/2) && scores[5] >= (standards[5]-(oneSDArr[5]-standards[5])/2) && !bResponse){
            /**
             * –4 或 5 个维度得分大于平均值，
             * –趋避性或适应性必须大于一个标准差
             * –活动水平不高于 1/2 标准差
             * –情绪本质不低于 1/2 个标准差
             */
            result = "启动缓慢型";
        } else if ((greatStandardCount >=4 && bResponse && greatOneSDCount==1)){
            /**
             * 中间偏难型
             * –4 或 5 个维度得分大于平均值(包括反应强度)，有一个维度大于一个标准差.
             */
            result = "中间偏难型";
        }else {
//            if (( (greatStandardCount ==4 || greatStandardCount ==5) && greatOneSDCount==0) || ((greatStandardCount ==4 || greatStandardCount ==5) && !bResponse && greatOneSDCount==1)
//                    || ((greatStandardCount ==2 || greatStandardCount==3) && greatOneSDCount<=3) || doubleGreatCount==1)
            /**
             * 中间偏易型
             * –4 或 5 个维度得分大于平均值，没有一个大于一个标准差 
             * –4 或 5 个维度得分大于平均值(不包括反应强度)，且有一个大于标准差。
             *  –2 或 3 个维度得分大于平均值，0-3 个维度大于一个标准差 
             *  –1 个维度大于平均值，且大于一个标准差
             */
            result = "中间偏易型";
        }

        return result;
    }
    /**
     *     * 1）活动水平 a<A-1SD 较弱 A-1SD<a< A+1SD 适中 a> A+1SD 较高
     *      * 2）规律性 a<A-1SD 较强 A-1SD<a< A+1SD 适中 a> A+1SD 较弱
     *      * 3）趋避性 a<A-1SD 易接近 A-1SD<a< A+1SD 适中 a> A+1SD 易退缩
     *      * 4）适应性 a<A-1SD 较强 A-1SD<a< A+1SD 适中 a> A+1SD 较弱
     *      * 5）反应强度 a<A-1SD 较弱 A-1SD<a< A+1SD 适中 a> A+1SD 较强
     *      * 6）情绪本质 a<A-1SD 较积极 A-1SD<a< A+1SD 适中 a> A+1SD 较消极
     *      * 7）坚持性 a<A-1SD 较高 A-1SD<a< A+1SD 适中 a> A+1SD 较低
     *      * 8）注意分散度 a<A-1SD 较易分散 A-1SD<a< A+1SD 适中 a> A+1SD 不易分散
     *      * 9）反应阈 a<A-1SD 较高 A-1SD<a< A+1SD 适中 a> A+1SD 较低
     * @param dimension 维度
     * @param score 分数
     * @param aa1SD  +1 标准差
     * @param as1Sd  -1 标准差
     * @return
     */
    private String temperamentCnType(Integer dimension, String score, Double a, Double aa1SD, Double as1Sd){
        String result = "适中";
        Double dScore = Double.valueOf(score);
        switch (dimension){
            case 1:
                if(dScore < as1Sd) {
                    result = "较弱";
                } else if (dScore > aa1SD) {
                    result = "较高";
                }
                break;
            case 2:
                if(dScore < as1Sd) {
                    result = "较强";
                } else if (dScore > aa1SD) {
                    result = "较弱";
                }
                break;
            case 3:
                if(dScore < as1Sd ) {
                    result = "易接近";
                } else if (dScore > aa1SD) {
                    result = "易退缩";
                }
                break;
            case 4:
                if(dScore < as1Sd ) {
                    result = "较强";
                }else if (dScore > aa1SD) {
                    result = "较弱";
                }
                break;
            case 5:
                if(dScore < as1Sd) {
                    result = "较弱";
                } else if (dScore > aa1SD) {
                    result = "较强";
                }
                break;
            case 6:
                if(dScore < as1Sd) {
                    result = "较积极";
                } else if (dScore > aa1SD) {
                    result = "较消极";
                }
                break;
            case 7:
                if(dScore < as1Sd) {
                    result = "较高";
                } else if (dScore > aa1SD) {
                    result = "较低";
                }
                break;
            case 8:
                if(dScore < as1Sd) {
                    result = "不易分散";
                } else if (dScore > aa1SD) {
                    result = "较易分散";
                }
                break;
            case 9:
                if(dScore < as1Sd) {
                    result = "较高";
                } else if (dScore > aa1SD) {
                    result = "较低";
                }
                break;
        }
        return result;
    }
    /**
     * 注意力测评报告
     */
    private JSONObject getReportOfAttention(EvalResultEntity entity, boolean isReport) {
        JSONObject result = new JSONObject();
        Integer tableId = entity.getTableId();
        EvalTableEntity table = evalTableService.getById(tableId);
        String sortCnName = table.getSortCn().concat("&混合");
        String[] sortCnArray = sortCnName.split("&");
        result.put("cnArray", sortCnArray);
        String answerStatistic = entity.getAnswerStatistic();
        JSONArray jsonArray = JSONArray.parseArray(answerStatistic);
        ArrayList<String> scoreArray = new ArrayList<>();
        JSONArray tableArray = new JSONArray();
        JSONArray tableResultArray = new JSONArray();
        for (int i = 0; i < jsonArray.size(); i++) {
            JSONObject jsonObject = jsonArray.getJSONObject(i);
            for (String s : jsonObject.keySet()) {
                String score = jsonObject.getString(s);
                scoreArray.add(score);

                JSONObject object = new JSONObject();
                if(isReport) {
                    object.put("report", this.getDimensionReport(tableId, Integer.parseInt(s), Integer.parseInt(score), ""));
                }
                JSONObject resultObj = new JSONObject();
                //手机端显示结果用
                resultObj.put("reportResult", this.getDimensionReportOnlyResult(tableId, Integer.parseInt(s), Integer.parseInt(score), ""));
                tableResultArray.add(resultObj);
                tableArray.add(object);
            }
        }

        Integer  mix = Integer.parseInt((String)scoreArray.get(0)) + Integer.parseInt((String)scoreArray.get(1));
        scoreArray.add(mix.toString());
        result.put("scoreArray", scoreArray);
        result.put("tableResultArray", tableResultArray);
        result.put("report", tableArray);
        return result;
    }

    private String getMSOfFeelingIntegrationItem(String dimension, Integer score) {
        String[] resultEndArray = {"失衡", "不良", "失调", "不足"};
        Integer index = Integer.valueOf(dimension) - 1;
        String resultEnd = resultEndArray[index];
        String resultStart = "正常";
        if (score < 20) {
            resultStart = "重度";
        } else if (score < 30) {
            resultStart = "中度";
        } else if (score <= 40) {
            resultStart = "轻度";
        }
        if(score > 40){
            //如果正常 就没有后缀了
            resultEnd = "";
        }

        return resultStart + resultEnd;
    }

    private Integer getMonths(Date befDate, Date aftDate) {
        Calendar bef = Calendar.getInstance();
        Calendar aft = Calendar.getInstance();
        bef.setTime(befDate);
        aft.setTime(aftDate);
        int result = aft.get(Calendar.MONTH) - bef.get(Calendar.MONTH);
        int month = (aft.get(Calendar.YEAR) - bef.get(Calendar.YEAR)) * 12;
        return Math.abs(month + result);
    }

    @Autowired
    private EvalQuestionService evalQuestionService;
    @Autowired
    private EvalTableService evalTableService;
    @Autowired
    private MemberService memberService;
    @Autowired
    private DictExtService dictExtService;
    @Autowired
    private EvalMatchService evalMatchService;
    @Autowired
    private RedisUtils redisUtils;
}
